/*-------------------------<-- Start of Description -->-------------------------*\ | PURPOSE: This macro completes a statistical analysis of many variables and | | prints the output on one page. Basically, it is a PROC UNIVARIATE | | with an output that looks like PROC MEANS. | |--------------------------<-- End of Description -->----------------------------| |--------------------------------------------------------------------------------| |------------------------<-- Start of Files Created -->--------------------------| | SYNTAX: %univ (indata = _dataset_name_, | | outdata = _output_dataset_, | | var = _variable_list_, | | round = _rounding_descriptor_, | | by = _by_variable_, | | stats = _statistics_to_print_) | \-------------------------<-- End of Files Created-->---------------------------*/ %macro univ(indata=, var=, outdata=contents, round=.01, by=, stats=_STD_) / des='Univariate statistics on one page'; %let notes=%sysfunc(getoption(notes, keyword)); options nonotes; %let starttime=%sysfunc(datetime()); %local i dataset v round by bye pageby var fn stats bn lb; /*----------------\ | assign defaults | \----------------*/ %let the_end = N; %if (%quote(&indata) = %quote()) %then %do; %let indata = %upcase(%scan(&sysdsn, 1).%scan(&sysdsn, 2)); options ¬es; %put NOTE: No datasets are specified. The dataset &indata will be used.; options nonotes; %end; %else %let indata = %data(&indata); %if (%quote(&var) = %quote()) %then %do; proc contents data=&indata out=contents(keep=name type) noprint; run; data _null_; set contents (where = (type=1)); call symput ('var'||trim(left(_n_)), trim(left(name))); call symput ('fn', trim(left(_n_))); run; %do i = 1 %to &fn; %let var = &var &&var&i; %end; %end; %else %let fn = %wordcnt(&var); /*------------------------------------------------------------\ | Calculate value of BY and PAGEBY--if by value is not %str() | \------------------------------------------------------------*/ %if (%quote(&by) ne %quote()) %then %do; %let bn = %words(&by); %let lb = %scan(&by, &bn, %str( )); %let pageby = %str(pageby &lb ;); %let bye = %str(by &by ;); %end; /*--------------------------------------------\ | If keywards are not used in the macro call, | | this section assigns keywords based on | | option _STD_ (standard) or _ALL_ (all). | \--------------------------------------------*/ %if %upcase(&stats) = _STD_ %then %let stats = n mean std cv sum min p10 p25 p50 p75 p90 max; %else %if %upcase(&stats) = _ALL_ %then %let stats = n nobs nmiss mean mode sum std cv css uss qrange msign normal stdmean probn probm probs signrank t kurtosis skewness range qrange sumwgt min p1 p5 p10 p25 p50 p75 p90 p95 p99 max; /*-------------------------------------\ | Use PROC CONTENTS to get label names | \-------------------------------------*/ proc contents data=&indata(keep=&var &by) out=contents(keep=name label) noprint; run; %let data_id = %sysfunc(open(&indata, i)); %do I = 1 %to &fn; %let label&i = %sysfunc(varlabel(&data_id, %sysfunc(varnum(&data_id, %scan(&var, &i, %str( )))))); %end; %let rc = %sysfunc(close(&data_id)); /*-------------------------------------------------\ | Univariate step writes out to dataset macro.temp | \-------------------------------------------------*/ proc univariate data=&indata noprint; &bye var &var; output out = temp n = %_prefix(prefix=n, from=1, to=&FN) mean = %_prefix(prefix=mean, from=1, to=&FN) std = %_prefix(prefix=std, from=1, to=&FN) cv = %_prefix(prefix=cv, from=1, to=&FN) min = %_prefix(prefix=min, from=1, to=&FN) p1 = %_prefix(prefix=p1_, from=1, to=&FN) p5 = %_prefix(prefix=p5_, from=1, to=&FN) p10 = %_prefix(prefix=p10_, from=1, to=&FN) q1 = %_prefix(prefix=p25_, from=1, to=&FN) median = %_prefix(prefix=p50_, from=1, to=&FN) q3 = %_prefix(prefix=p75_, from=1, to=&FN) p90 = %_prefix(prefix=p90_, from=1, to=&FN) p95 = %_prefix(prefix=p95_, from=1, to=&FN) p99 = %_prefix(prefix=p99_, from=1, to=&FN) max = %_prefix(prefix=max, from=1, to=&FN) sum = %_prefix(prefix=sum, from=1, to=&FN) kurtosis = %_prefix(prefix=kurt, from=1, to=&FN) skewness = %_prefix(prefix=skew, from=1, to=&FN) css = %_prefix(prefix=css, from=1, to=&FN) nmiss = %_prefix(prefix=nmiss, from=1, to=&FN) msign = %_prefix(prefix=msign, from=1, to=&FN) nobs = %_prefix(prefix=nobs, from=1, to=&FN) qrange = %_prefix(prefix=qrang, from=1, to=&FN) t = %_prefix(prefix=t, from=1, to=&FN) normal = %_prefix(prefix=norm, from=1, to=&FN) sumwgt = %_prefix(prefix=sumwt, from=1, to=&FN) stdmean = %_prefix(prefix=stdmn, from=1, to=&FN) probn = %_prefix(prefix=probn, from=1, to=&FN) range = %_prefix(prefix=range, from=1, to=&FN) var = %_prefix(prefix=var, from=1, to=&FN) probm = %_prefix(prefix=probm, from=1, to=&FN) mode = %_prefix(prefix=mode, from=1, to=&FN) signrank = %_prefix(prefix=sign, from=1, to=&FN) uss = %_prefix(prefix=uss, from=1, to=&FN) probs = %_prefix(prefix=probs, from=1, to=&FN) ; run ; /*--------------------------------------------------------------\ | transpose the dataset macro.temp to be printed, round values, | | add labels, format the label descriptor, and keep variables | \--------------------------------------------------------------*/ data &outdata (keep = varname label min p1 p5 p10 p25 p50 p75 p90 p95 p99 max kurtosis n skewness css nmiss std msign mean nobs sum qrange t normal sumwgt stdmean probn range cv probm mode signrank uss probs &by); set temp; label label = 'Variable description' varname = 'Variable name' n = 'Number non-missing values' mean = 'Mean value' sum = 'Sum of all values' std = 'Standard deviation' cv = 'Coefficient of variation' min = 'Minimum value' p1 = '1st %tile' p5 = '5th %tile' p10 = '10th %tile' p25 = '25th %tile' p50 = '50th %tile' p75 = '75th %tile' p90 = '90th %tile' p95 = '95th %tile' p99 = '99th %tile' max = 'Maximum value' kurtosis = 'Kurtosis' skewness = 'Skewness' css = 'Corrected sum of squares' nmiss = 'Number missing values' msign = 'Sign statistic' nobs = 'Number observations' qrange = 'Inter-quartile range' T = "Student's T" normal = 'Normality test statistic' sumwgt = 'Sum of the weights' stdmean = 'Standard mean' probn = 'P-value of normality test statistic' range = 'Range of values' var = 'Variance' probm = 'P-value of sign statistic' mode = 'Most frequent value' signrank = 'Signed Rank Statistic' uss = 'Uncorrected sum of squares' probs = 'P-value of signed ranked statistic' ; length label $40 varname $8 ; /*------------------------------------\ | This section mimmics PROC TRANSPOSE | \------------------------------------*/ %do I = 1 %to &fn; varname = "%scan(&var, &i, %str( ))"; label = "&&label&i"; if label = '' then label = left(varname); n = n&i; mean = round(mean&i, &round); sum = round(sum&i, &round); std = round(std&i, &round); cv = round(cv&i, &round); min = round(min&i, &round); P1 = round(P1_&i, &round); P5 = round(P5_&i, &round); P10 = round(P10_&i, &round); P25 = round(P25_&i, &round); P50 = round(P50_&i, &round); P75 = round(P75_&i, &round); P90 = round(P90_&i, &round); P95 = round(P95_&i, &round); P99 = round(P99_&i, &round); max = round(max&i, &round); kurtosis = round(kurt&i, &round); skewness = round(skew&i, &round); css = round(css&i, &round); nmiss = round(nmiss&i, &round); msign = round(msign&i, &round); nobs = round(nobs&i, &round); qrange = round(qrang&i, &round); T = round(T&i, &round); normal = round(norm&i, &round); sumwgt = round(sumwt&i, &round); stdmean = round(stdmn&i, &round); probn = round(probn&i, &round); range = round(range&i, &round); var = round(var&i, &round); probm = round(probm&i, &round); mode = round(mode&i, &round); signrank = round(sign&i, &round); uss = round(uss&i, &round); probs = round(probs&i, &round); output ; %end; run; /*------------------------------------------------------\ | If by-variables are used, sort the transposed dataset | \------------------------------------------------------*/ %if &by ne %str() %then %do ; proc sort data=&outdata; by &by; run; %end ; /*-----------------------------------\ | PROC PRINT is used to print output | \-----------------------------------*/ proc print data=&outdata noobs label; &bye &pageby id varname; var label &stats; run; /*-----------------------------------------\ | Delete temporary datasets and data views | \-----------------------------------------*/ proc datasets lib=macro nolist memtype=(data view); delete contents view1 temp; run; quit; /*--------------------------------------\ | Prepare the SAS session for open code | \--------------------------------------*/ %put NOTE: Macro UNIV printed statistics for variabes %upcase(&var).; %if (%quote(%upcase(&outdata)) ne %quote(CONTENTS)) %then %do ; %let outobs = %nobs(&outdata); %let outvar = %nvars(&outdata); options ¬es; %put NOTE: The dataset %data(&outdata) has &outobs observations and &outvar variables.; options nonotes; %end ; %timenote (macro=univ,starttime=&starttime) options ¬es; %mend univ;